using System;
using System.Collections.Generic;
using Firestarter.DB.Schema.BO;
using Firestarter.DB_DomainModel.Logic;
using FireStarterModeller.BO;
using FireStarterModeller.UI;
using FireStarterModeller.UI.CodeGeneration;
using Habanero.Base;
using Habanero.BO;
using Habanero.Faces.Base;

namespace Firestarter.DB.Schema.UI
{
    public class DbSchemaReverseEngineerWizardController : WizardController
    {
        private readonly IDBChangesImporter _dbChangesImporter;
        private ReverseEngineering _reverseEngineering;
        private readonly ChooseDatabaseConnectionWizardStep _step1;
        private readonly ChooseObjectTypesWizardStep _step2;
        private readonly ApproveSchemaChangesWizardStep _step3;
        //private readonly ApproveModelModificationsWizardStep _step4;
        internal IFireStarterFormsController FireStarterFormsController { get; private set; }

        public DbSchemaReverseEngineerWizardController(IFireStarterFormsController fireStarterFormsController, ReverseEngineering reverseEngineering, IDBChangesImporter dbChangesImporter)
        {
            this.FireStarterFormsController = fireStarterFormsController;
            _dbChangesImporter = dbChangesImporter;
            _step1 = new ChooseDatabaseConnectionWizardStep();
            _step2 = new ChooseObjectTypesWizardStep();
            _step3 = new ApproveSchemaChangesWizardStep();
            //_step4 = new ApproveModelModificationsWizardStep();
            AddStep(_step1);
            AddStep(_step2);
            AddStep(_step3);
            //AddStep(_step4);
            ReverseEngineering = reverseEngineering;
        }

        public IDBChangesImporter DbChangesImporter
        {
            get { return _dbChangesImporter; }
        }

        public ReverseEngineering ReverseEngineering
        {
            get
            {
                return _reverseEngineering;
            }
            set
            {
                _reverseEngineering = value;
                
                _step1.ReverseEngineering = value;
                _step2.ReverseEngineering = value;
                _step3.ReverseEngineering = value;
                _step3.ReverseEngineering = value;
            }
        }

        public ChooseDatabaseConnectionWizardStep Step1
        {
            get { return _step1; }
        }

        public ChooseObjectTypesWizardStep Step2
        {
            get { return _step2; }
        }

        public ApproveSchemaChangesWizardStep Step3
        {
            get { return _step3; }
        }

        

        //public ApproveModelModificationsWizardStep Step4
        //{
        //    get { return _step4; }
        //}

        public override void Finish()
        {
            

            try
            {
                
                IList<IBOError> errors = _dbChangesImporter.ImportDBChanges(ReverseEngineering.StoredDatabase, ReverseEngineering.GetSolution());

                if (errors.Count > 0)
                {
                    IFormHabanero form = FireStarterFormsController.CreateShowErrorsForm(errors, "Warnings Reported",
                        "There were warnings reported when applying the database changes to the domain model.",
                        "Would you like to continue in spite of these warnings?");
                    form.ShowDialog();
                }
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "Error applying database changes to the domain model.", "Error Applying Changes");
                CancelChanges();
            }
        }

        private void CancelChanges()
        {
            try
            {
                ReverseEngineering.StoredDatabase.CancelEdits();
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "CRITICAL ERROR: Error canceling database changes.", "Error Canceling Changes");
            }
            try
            {
                ReverseEngineering.StoredDatabase.CancelEdits();
                ReverseEngineering.GetSolution().CancelEdits();
            }
            catch (Exception ex)
            {
                GlobalRegistry.UIExceptionNotifier.Notify(ex, "CRITICAL ERROR: Error canceling domain model changes.", "Error Canceling Changes");
            }
        }
    }
}
